AJS.copyObject = function (object, deep) {
    var copiedObject = {};
    AJS.$.each(object, function (name, property) {
        if (typeof property !== "object" || property === null || property instanceof AJS.$) {
            copiedObject[name] = property
        } else {
            if (deep !== false) {
                copiedObject[name] = AJS.copyObject(property, deep)
            }
        }
    });
    return copiedObject
};
var JIRA = window.JIRA || {};
AJS.namespace = function (namespace, context, value) {
    var names = namespace.split(".");
    context = context || window;
    for (var i = 0, n = names.length - 1; i < n; i++) {
        var x = context[names[i]];
        context = (x != null) ? x : context[names[i]] = {}
    }
    return context[names[i]] = value || {}
};
AJS.canAccessIframe = function (iframe) {
    var $iframe = AJS.$(iframe);
    return !/^(http|https):\/\//.test($iframe.attr("src")) || (AJS.params.baseURL && (AJS.$.trim($iframe.attr("src")).indexOf(AJS.params.baseURL) === 0))
};
(function () {
    function preventScrolling(e) {
        var keyCode = e.keyCode,
            keys = AJS.$.ui.keyCode;
        if (!jQuery(e.target).is("textarea, :text, select") && (keyCode === keys.DOWN || keyCode === keys.UP || keyCode === keys.LEFT || keyCode === keys.RIGHT)) {
            e.preventDefault()
        }
    }
    AJS.disableKeyboardScrolling = function () {
        AJS.$(document).bind("keypress keydown", preventScrolling)
    };
    AJS.enableKeyboardScrolling = function () {
        AJS.$(document).unbind("keypress keydown", preventScrolling)
    }
})();
AJS.$.namespace = function (namespace) {
    return AJS.namespace(namespace)
};
jQuery.noConflict();
jQuery.ajaxSettings.traditional = true;
contextPath = typeof contextPath === "undefined" ? "" : contextPath;
AJS.LEFT = "left";
AJS.RIGHT = "right";
AJS.ACTIVE_CLASS = "active";
AJS.BOX_SHADOW_CLASS = "box-shadow";
AJS.LOADING_CLASS = "loading";
AJS.INTELLIGENT_GUESS = "Intelligent Guess";
AJS.DIRTY_FORM_VALUE = "AJS_DirtyForms_cleanValue";
(function () {
    var SPECIAL_CHARS = /[.*+?|^$()[\]{\\]/g;
    RegExp.escape = function (str) {
        return str.replace(SPECIAL_CHARS, "\\$&")
    }
})();
(function ($) {
    $.readData = function (s) {
        var r = {},
            n = "";
        $(s).children().each(function (i) {
            if (i % 2) {
                r[n] = jQuery.trim($(this).text())
            } else {
                n = jQuery.trim($(this).text())
            }
        }).remove();
        $(s).remove();
        return r
    }
})(jQuery);
String.prototype.escapejQuerySelector = function () {
    return this.replace(/([:.])/g, "\\$1")
};
AJS.trigger = function (event, target) {
    event = new jQuery.Event(event);
    jQuery(target || window.top.document).trigger(event);
    return !event.isDefaultPrevented()
};
jQuery.aop.after({
    target: jQuery,
    method: "append"
}, function (elem) {
    var iframes;
    if (elem.attr("tagName") === "iframe" && AJS.canAccessIframe(elem)) {
        if (!elem.data("iframeAppendedFired")) {
            elem.data("iframeAppendedFired", true);
            jQuery(document).trigger("iframeAppended", elem)
        }
    }
    iframes = jQuery("iframe", elem);
    if (iframes.length > 0) {
        jQuery.each(iframes, function (i) {
            var iframe = iframes.eq(i);
            if (!iframe.data("iframeAppendedFired") && AJS.canAccessIframe(iframe)) {
                iframe.data("iframeAppendedFired", true);
                jQuery(document).trigger("iframeAppended", iframe)
            }
        })
    }
    return elem
});
AJS.isSelenium = function () {
    var detectOn = function (obj) {
            for (var propName in obj) {
                if (propName.indexOf("selenium") != -1) {
                    return true
                }
            }
            return false
        };
    return detectOn(window.location) || detectOn(window)
};
AJS.reloadViaWindowLocation = function (url) {
    var windowReload = function () {
            window.location.reload()
        };
    url = url || window.location.href;
    if (AJS.isSelenium()) {
        windowReload()
    } else {
        var makeHashUrlsUnique = function (url) {
                var MAGIC_PARAM = "jwupdated";
                var hashIndex = url.indexOf("#");
                if (hashIndex == -1) {
                    return url
                }
                var secondsSinceMidnight = function () {
                        var now = new Date();
                        var midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
                        var secs = (now.getTime() - midnight.getTime()) / 1000;
                        return Math.max(Math.floor(secs), 1)
                    };
                var firstQuestionMark = url.indexOf("?");
                var magicParamValue = MAGIC_PARAM + "=" + secondsSinceMidnight();
                if (firstQuestionMark == -1) {
                    url = url.replace("#", "?" + magicParamValue + "#")
                } else {
                    if (url.indexOf(MAGIC_PARAM + "=") != -1) {
                        url = url.replace(/(jwupdated=[0-9]+)/, magicParamValue)
                    } else {
                        url = url.replace("?", "?" + magicParamValue + "&")
                    }
                }
                return url
            };
        url = makeHashUrlsUnique(url);
        if (jQuery.browser.webkit && parseInt(jQuery.browser.version) < 533) {
            window.location = url
        } else {
            window.location.replace(url)
        }
    }
};
AJS.extractBodyFromResponse = function (text) {
    var fragment = text.match(/<body[^>]*>([\S\s]*)<\/body[^>]*>/);
    if (fragment && fragment.length > 0) {
        return fragment[1]
    }
    return text
};
(function () {
    var SPECIAL_CHARS = /[&"<]/g;
    AJS.escapeHTML = function (str) {
        return str.replace(SPECIAL_CHARS, replacement)
    };

    function replacement(specialChar) {
        switch (specialChar) {
        case "<":
            return "&lt;";
        case "&":
            return "&amp;";
        default:
            return "&quot;"
        }
    }
})();

function tryIt(f, defaultVal) {
    try {
        return f()
    } catch (ex) {
        return defaultVal
    }
}
function begetObject(obj) {
    var f = function () {};
    f.prototype = obj;
    return new f
}
function submitOnEnter(e) {
    if (e.keyCode == 13 && e.target.form && !e.ctrlKey && !e.shiftKey) {
        jQuery(e.target.form).submit();
        return false
    }
    return true
}
function submitOnCtrlEnter(e) {
    if (e.ctrlKey && e.target.form && (e.keyCode == 13 || e.keyCode == 10)) {
        jQuery(e.target.form).submit();
        return false
    }
    return true
}
function getMultiSelectValues(selectObject) {
    var selectedValues = "";
    for (var i = 0; i < selectObject.length; i++) {
        if (selectObject.options[i].selected) {
            if (selectObject.options[i].value && selectObject.options[i].value.length > 0) {
                selectedValues = selectedValues + " " + selectObject.options[i].value
            }
        }
    }
    return selectedValues
}
function getMultiSelectValuesAsArray(selectObject) {
    var selectedValues = new Array();
    for (var i = 0; i < selectObject.length; i++) {
        if (selectObject.options[i].selected) {
            if (selectObject.options[i].value && selectObject.options[i].value.length > 0) {
                selectedValues[selectedValues.length] = selectObject.options[i].value
            }
        }
    }
    return selectedValues
}
function arrayContains(array, value) {
    for (var i = 0; i < array.length; i++) {
        if (array[i] == value) {
            return true
        }
    }
    return false
}
function addClassName(elementId, classNameToAdd) {
    var elem = document.getElementById(elementId);
    if (elem) {
        elem.className = elem.className + " " + classNameToAdd
    }
}
function removeClassName(elementId, classNameToRemove) {
    var elem = document.getElementById(elementId);
    if (elem) {
        elem.className = (" " + elem.className + " ").replace(" " + classNameToRemove + " ", " ")
    }
}
function getEscapedFieldValue(id) {
    var e = document.getElementById(id);
    if (e.value) {
        return id + "=" + encodeURIComponent(e.value)
    } else {
        return ""
    }
}
function getEscapedFieldValues(ids) {
    var s = "";
    for (var i = 0; i < ids.length; i++) {
        s = s + "&" + getEscapedFieldValue(ids[i])
    }
    return s
}
var GuiPrefs = {
    toggleVisibility: function (elementId) {
        var elem = document.getElementById(elementId);
        if (elem) {
            if (readFromConglomerateCookie("jira.conglomerate.cookie", elementId, "1") == "1") {
                elem.style.display = "none";
                removeClassName(elementId + "header", "headerOpened");
                addClassName(elementId + "header", "headerClosed");
                saveToConglomerateCookie("jira.conglomerate.cookie", elementId, "0")
            } else {
                elem.style.display = "";
                removeClassName(elementId + "header", "headerClosed");
                addClassName(elementId + "header", "headerOpened");
                eraseFromConglomerateCookie("jira.conglomerate.cookie", elementId)
            }
        }
    }
};

function toggle(elementId) {
    GuiPrefs.toggleVisibility(elementId)
}
function toggleDivsWithCookie(elementShowId, elementHideId) {
    var elementShow = document.getElementById(elementShowId);
    var elementHide = document.getElementById(elementHideId);
    if (elementShow.style.display == "none") {
        elementHide.style.display = "none";
        elementShow.style.display = "block";
        saveToConglomerateCookie("jira.viewissue.cong.cookie", elementShowId, "1");
        saveToConglomerateCookie("jira.viewissue.cong.cookie", elementHideId, "0")
    } else {
        elementShow.style.display = "none";
        elementHide.style.display = "block";
        saveToConglomerateCookie("jira.viewissue.cong.cookie", elementHideId, "1");
        saveToConglomerateCookie("jira.viewissue.cong.cookie", elementShowId, "0")
    }
}
function restoreDivFromCookie(elementId, cookieName, defaultValue) {
    if (defaultValue == null) {
        defaultValue = "1"
    }
    var elem = document.getElementById(elementId);
    if (elem) {
        if (readFromConglomerateCookie(cookieName, elementId, defaultValue) != "1") {
            elem.style.display = "none";
            removeClassName(elementId + "header", "headerOpened");
            addClassName(elementId + "header", "headerClosed")
        } else {
            elem.style.display = "";
            removeClassName(elementId + "header", "headerClosed");
            addClassName(elementId + "header", "headerOpened")
        }
    }
}
function restore(elementId) {
    restoreDivFromCookie(elementId, "jira.conglomerate.cookie", "1")
}
function saveToConglomerateCookie(cookieName, name, value) {
    var cookieValue = getCookieValue(cookieName);
    cookieValue = addOrAppendToValue(name, value, cookieValue);
    saveCookie(cookieName, cookieValue, 365)
}
function readFromConglomerateCookie(cookieName, name, defaultValue) {
    var cookieValue = getCookieValue(cookieName);
    var value = getValueFromCongolmerate(name, cookieValue);
    if (value != null) {
        return value
    }
    return defaultValue
}
function eraseFromConglomerateCookie(cookieName, name) {
    saveToConglomerateCookie(cookieName, name, "")
}
function getValueFromCongolmerate(name, cookieValue) {
    if (cookieValue == null) {
        cookieValue = ""
    }
    var eq = name + "=";
    var cookieParts = cookieValue.split("|");
    for (var i = 0; i < cookieParts.length; i++) {
        var cp = cookieParts[i];
        while (cp.charAt(0) == " ") {
            cp = cp.substring(1, cp.length)
        }
        if (cp.indexOf(name) == 0) {
            return cp.substring(eq.length, cp.length)
        }
    }
    return null
}
function addOrAppendToValue(name, value, cookieValue) {
    var newCookieValue = "";
    if (cookieValue == null) {
        cookieValue = ""
    }
    var cookieParts = cookieValue.split("|");
    for (var i = 0; i < cookieParts.length; i++) {
        var cp = cookieParts[i];
        if (cp != "") {
            while (cp.charAt(0) == " ") {
                cp = cp.substring(1, cp.length)
            }
            if (cp.indexOf(name) != 0) {
                newCookieValue += cp + "|"
            }
        }
    }
    if (value != null && value != "") {
        var pair = name + "=" + value;
        if ((newCookieValue.length + pair.length) < 4020) {
            newCookieValue += pair
        }
    }
    return newCookieValue
}
function getCookieValue(name) {
    var eq = name + "=";
    var ca = document.cookie.split(";");
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == " ") {
            c = c.substring(1, c.length)
        }
        if (c.indexOf(eq) == 0) {
            return unescape(c.substring(eq.length, c.length))
        }
    }
    return null
}
function saveCookie(name, value, days) {
    if (typeof contextPath === "undefined") {
        return
    }
    var path = contextPath;
    if (!path) {
        path = "/"
    }
    var ex;
    if (days) {
        var d = new Date();
        d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
        ex = "; expires=" + d.toGMTString()
    } else {
        ex = ""
    }
    document.cookie = name + "=" + escape(value) + ex + ";path=" + path
}
function readCookie(name, defaultValue) {
    var cookieVal = getCookieValue(name);
    if (cookieVal != null) {
        return cookieVal
    }
    if (defaultValue) {
        saveCookie(name, defaultValue, 365);
        return defaultValue
    } else {
        return null
    }
}
function eraseCookie(name) {
    saveCookie(name, "", -1)
}
function recolourSimpleTableRows(tableId) {
    recolourTableRows(tableId, "rowNormal", "rowAlternate", tableId + "_empty")
}
function recolourTableRows(tableId, rowNormal, rowAlternate, emptyTableId) {
    var tbl = document.getElementById(tableId);
    var emptyTable = document.getElementById(emptyTableId);
    var alternate = false;
    var rowsFound = 0;
    var rows = tbl.rows;
    var firstVisibleRow = null;
    var lastVisibleRow = null;
    if (AJS.$(tbl).hasClass("aui")) {
        rowNormal = "";
        rowAlternate = "zebra"
    }
    for (var i = 1; i < rows.length; i++) {
        var row = rows[i];
        if (row.style.display != "none") {
            if (!alternate) {
                row.className = rowNormal
            } else {
                row.className = rowAlternate
            }
            rowsFound++;
            alternate = !alternate
        }
        if (row.style.display != "none") {
            if (firstVisibleRow == null) {
                firstVisibleRow = row
            }
            lastVisibleRow = row
        }
    }
    if (firstVisibleRow != null) {
        firstVisibleRow.className = firstVisibleRow.className + " first-row"
    }
    if (lastVisibleRow != null) {
        lastVisibleRow.className = lastVisibleRow.className + " last-row"
    }
    if (emptyTable) {
        if (rowsFound == 0) {
            tbl.style.display = "none";
            emptyTable.style.display = ""
        } else {
            tbl.style.display = "";
            emptyTable.style.display = "none"
        }
    }
}
function htmlEscape(str) {
    var divE = document.createElement("div");
    divE.appendChild(document.createTextNode(str));
    return divE.innerHTML
}
function atl_token() {
    return jQuery("#atlassian-token").attr("content")
}
function openDateRangePicker(formName, previousFieldName, nextFieldName, fieldId) {
    var previousFieldValue = document.forms[formName].elements[previousFieldName].value;
    var nextFieldValue = document.forms[formName].elements[nextFieldName].value;
    var url = contextPath + "/secure/popups/DateRangePicker.jspa?";
    url += "formName=" + formName + "&";
    url += "previousFieldName=" + escape(previousFieldName) + "&";
    url += "nextFieldName=" + escape(nextFieldName) + "&";
    url += "previousFieldValue=" + escape(previousFieldValue) + "&";
    url += "nextFieldValue=" + escape(nextFieldValue) + "&";
    url += "fieldId=" + escape(fieldId);
    var vWinUsers = window.open(url, "DateRangePopup", "status=no,resizable=yes,top=100,left=200,width=580,height=400,scrollbars=yes");
    vWinUsers.opener = self;
    vWinUsers.focus()
}
function show_calendar2(formName, fieldName) {
    var form = document.forms[formName];
    var element = form.elements[fieldName];
    var vWinCal = window.open(contextPath + "/secure/popups/Calendar.jspa?form=" + formName + "&field=" + fieldName + "&value=" + escape(element.value) + "&decorator=none", "Calendar", "width=230,height=170,status=no,resizable=yes,top=220,left=200");
    vWinCal.opener = self;
    vWinCal.focus()
};
(function () {
    begetObject = function (obj) {
        var f = function () {};
        f.prototype = obj;
        return new f()
    };
    var initializing = false,
        fnTest = /xyz/.test(function () {
            xyz
        }) ? /\b_super\b/ : /.*/;
    this.Class = function () {};
    Class.extend = function () {
        var prop;
        var _super = this.prototype;
        if (arguments.length > 1) {
            var interfaces = AJS.$.makeArray(arguments);
            prop = interfaces.pop();
            var completeInterface;
            AJS.$.each(interfaces, function (i, inter) {
                if (completeInterface) {
                    completeInterface = completeInterface.extend(inter)
                } else {
                    completeInterface = inter
                }
            });
            return completeInterface.extend(this.prototype).extend(prop)
        } else {
            prop = arguments[0]
        }
        initializing = true;
        var prototype = new this();
        initializing = false;
        for (var name in prop) {
            if (prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])) {
                prototype[name] = (function (name, fn) {
                    return function () {
                        var tmp = this._super;
                        this._super = _super[name];
                        var ret = fn.apply(this, arguments);
                        this._super = tmp;
                        return ret
                    }
                })(name, prop[name])
            } else {
                if (typeof _super[name] === "object") {
                    var newObj = begetObject(prop[name]);
                    AJS.$.each(_super[name], function (name, obj) {
                        if (!newObj[name]) {
                            newObj[name] = obj
                        } else {
                            if (typeof newObj[name] === "object") {
                                var newSubObj = begetObject(newObj[name]);
                                AJS.$.each(obj, function (subName, subObj) {
                                    if (!newSubObj[subName]) {
                                        newSubObj[subName] = subObj
                                    }
                                });
                                newObj[name] = newSubObj
                            }
                        }
                    });
                    prototype[name] = newObj
                } else {
                    prototype[name] = prop[name]
                }
            }
        }
        function Class() {
            if (!initializing && this.init) {
                this.init.apply(this, arguments)
            }
        }
        Class.prototype = prototype;
        Class.constructor = Class;
        Class.extend = arguments.callee;
        return Class
    }
})();
AJS.Control = Class.extend({
    INVALID: "INVALID",
    _throwReadOnlyError: function (property) {
        new Error(this.CLASS_SIGNATURE + ": Sorry [" + property + "] is a read-only property")
    },
    _assignEvents: function (group, target) {
        var key, handlers;
        var instance = this;
        this._activeEvents = this._activeEvents || {};
        if (typeof target === "string") {
            key = group + "/" + target;
            if (this._activeEvents[key]) {
                return
            }
            handlers = this._activeEvents[key] = {};
            AJS.$.each(this._events[group], function (eventType, handler) {
                handlers[eventType] = function (event) {
                    handler.call(instance, event, AJS.$(this))
                };
                AJS.$(document).delegate(target, eventType, handlers[eventType])
            })
        } else {
            target = AJS.$(target);
            if (target.length === 0) {
                return
            }
            if (this._activeEvents[group + "/" + target[0][AJS.$.expando]]) {
                return
            }
            handlers = {};
            AJS.$.each(this._events[group], function (eventType, handler) {
                handlers[eventType] = function (event) {
                    handler.call(instance, event, AJS.$(this))
                };
                target.bind(eventType, handlers[eventType])
            });
            key = group + "/" + (target[0] === window ? "window" : target[0][AJS.$.expando]);
            this._activeEvents[key] = handlers
        }
    },
    _unassignEvents: function (group, target) {
        var key, handlers, eventType;
        this._activeEvents = this._activeEvents || {};
        if (typeof target === "string") {
            key = group + "/" + target;
            handlers = this._activeEvents[key];
            if (!handlers) {
                return
            }
            for (eventType in handlers) {
                AJS.$(document).undelegate(target, eventType, handlers[eventType])
            }
        } else {
            target = AJS.$(target);
            if (target.length === 0) {
                return
            }
            key = group + "/" + target[0][AJS.$.expando];
            handlers = this._activeEvents[key];
            if (!handlers) {
                return
            }
            try {
                for (eventType in handlers) {
                    target.unbind(eventType, handlers[eventType])
                }
            } catch (error) {
                var events = AJS.$.data(target[0], "events");
                if (events) {
                    for (eventType in handlers) {
                        var $handlers = events[eventType];
                        if (!$handlers) {
                            continue
                        }
                        var i = $handlers.length;
                        while (i--) {
                            if ($handlers[i].handler === handlers[eventType]) {
                                $handlers.splice(i, 1);
                                if ($handlers.length === 0) {
                                    delete events[eventType]
                                }
                                break
                            }
                        }
                    }
                }
            }
        }
        delete this._activeEvents[key]
    },
    _isValidInput: function () {
        return true
    },
    _handleKeyEvent: function (e) {
        var instance = this;
        if (instance._isValidInput(e)) {
            var SpecialKey = JIRA.Keyboard.SpecialKey,
                shortcut = JIRA.Keyboard.shortcutEntered(e);
            if (shortcut) {
                if (instance.keys[shortcut]) {
                    instance.keys[shortcut].call(instance, e);
                    return
                } else {
                    if ((shortcut === SpecialKey.BACKSPACE || shortcut === SpecialKey.DELETE) && instance.keys.onEdit) {
                        instance.keys.onEdit.call(instance, e);
                        return
                    }
                }
            }
            var character = JIRA.Keyboard.characterEntered(e);
            if (character && instance.keys.onEdit) {
                instance.keys.onEdit.call(instance, e, character)
            }
        }
    },
    getCustomEventName: function (methodName) {
        return (this.CLASS_SIGNATURE || "") + "_" + methodName
    },
    _getCustomEventArgs: function () {
        return [this]
    },
    trigger: function (event) {
        return AJS.trigger(event, this)
    },
    _supportsBoxShadow: function () {
        var s = document.body.style;
        return s.WebkitBoxShadow !== undefined || s.MozBoxShadow !== undefined || s.boxShadow !== undefined
    },
    _setOptions: function (options) {
        var element, optionsFromDOM;
        options = options || {};
        if (options instanceof AJS.$ || typeof options === "string" || (typeof options === "object" && options.nodeName)) {
            options = {
                element: options
            }
        }
        element = AJS.$(options.element);
        optionsFromDOM = element.getOptionsFromAttributes();
        this.options = AJS.$.extend(true, this._getDefaultOptions(options), optionsFromDOM, options);
        if (element.length === 0) {
            return this.INVALID
        }
        return undefined
    },
    getCaret: function (node) {
        var startIndex = node.selectionStart;
        if (startIndex >= 0) {
            return (node.selectionEnd > startIndex) ? -1 : startIndex
        }
        if (document.selection) {
            var textRange1 = document.selection.createRange();
            if (textRange1.text.length === 0) {
                var textRange2 = textRange1.duplicate();
                textRange2.moveToElementText(node);
                textRange2.setEndPoint("EndToStart", textRange1);
                return textRange2.text.length
            }
        }
        return -1
    },
    _render: function () {
        var i, name = arguments[0],
            args = [];
        for (i = 1; i < arguments.length; i++) {
            args.push(arguments[i])
        }
        return this._renders[name].apply(this, args)
    }
});
AJS.Descriptor = Class.extend({
    init: function (properties) {
        if (this._validate(properties)) {
            this.properties = AJS.$.extend(this._getDefaultOptions(), properties)
        }
    },
    allProperties: function () {
        return this.properties
    },
    _validate: function (properties) {
        if (this.REQUIRED_PROPERTIES) {
            AJS.$.each(this.REQUIRED_PROPERTIES, function (name) {
                if (typeof properties[name] === "undefined") {
                    throw new Error("AJS.Descriptor: expected property [" + name + "] but was undefined")
                }
            })
        }
        return true
    }
});
JIRA.Keyboard = {};
(function ($) {
    var _keyCodeToEnum = {},
        _enumToKeyCode = {},
        _keyCodeToIsAscii = {};
    var SpecialKey = JIRA.Keyboard.SpecialKey = {
        BACKSPACE: specialKey("backspace", 8, true),
        TAB: specialKey("tab", 9, true),
        RETURN: specialKey("return", 13, true),
        SHIFT: specialKey("shift", 16),
        CTRL: specialKey("ctrl", 17),
        ALT: specialKey("alt", 18),
        PAUSE: specialKey("pause", 19),
        CAPS_LOCK: specialKey("capslock", 20),
        ESC: specialKey("esc", 27, true),
        SPACE: specialKey("space", 32, true),
        PAGE_UP: specialKey("pageup", 33),
        PAGE_DOWN: specialKey("pagedown", 34),
        END: specialKey("end", 35),
        HOME: specialKey("home", 36),
        LEFT: specialKey("left", 37),
        UP: specialKey("up", 38),
        RIGHT: specialKey("right", 39),
        DOWN: specialKey("down", 40),
        INSERT: specialKey("insert", 45),
        DELETE: specialKey("del", 46),
        F1: specialKey("f1", 112),
        F2: specialKey("f2", 113),
        F3: specialKey("f3", 114),
        F4: specialKey("f4", 115),
        F5: specialKey("f5", 116),
        F6: specialKey("f6", 117),
        F7: specialKey("f7", 118),
        F8: specialKey("f8", 119),
        F9: specialKey("f9", 120),
        F10: specialKey("f10", 121),
        F11: specialKey("f11", 122),
        F12: specialKey("f12", 123),
        NUMLOCK: specialKey("numlock", 144),
        SCROLL: specialKey("scroll", 145),
        META: specialKey("meta", 224)
    };

    function specialKey(name, keyCode, isAscii) {
        _keyCodeToEnum[keyCode] = name;
        _enumToKeyCode[name] = keyCode;
        if (isAscii) {
            _keyCodeToIsAscii[keyCode] = true
        }
        return name
    }
    SpecialKey.eventType = function () {
        return $.browser.mozilla ? "keypress" : "keydown"
    };
    SpecialKey.fromKeyCode = function (keyCode) {
        return _keyCodeToEnum[keyCode]
    };
    SpecialKey.toKeyCode = function (specialKey) {
        return _enumToKeyCode[specialKey]
    };
    SpecialKey.isAscii = function (keyCode) {
        return !!_keyCodeToIsAscii[keyCode]
    };
    SpecialKey.isSpecialKey = function (keyName) {
        return !!SpecialKey.toKeyCode(keyName)
    };

    function originalEvent(e) {
        return e.originalEvent || e
    }
    JIRA.Keyboard.characterEntered = function (keypressEvent) {
        var e = originalEvent(keypressEvent);
        if (e.type === "keypress") {
            var characterCode = characterCodeForKeypress(e);
            if (characterCode !== null && (!SpecialKey.isAscii(characterCode) || SpecialKey.fromKeyCode(characterCode) === SpecialKey.SPACE)) {
                return String.fromCharCode(characterCode)
            }
        }
        return undefined
    };

    function characterCodeForKeypress(keypressEvent) {
        var e = originalEvent(keypressEvent);
        if (e.which == null) {
            return e.keyCode
        } else {
            if (e.which != 0 && e.charCode != 0) {
                return e.which
            } else {
                return null
            }
        }
    }
    JIRA.Keyboard.specialKeyEntered = function (e) {
        e = originalEvent(e);
        if ($.browser.mozilla) {
            if (e.type === "keypress") {
                var characterCode = characterCodeForKeypress(e);
                if (characterCode === null) {
                    return SpecialKey.fromKeyCode(e.keyCode)
                } else {
                    if (SpecialKey.isAscii(characterCode)) {
                        return SpecialKey.fromKeyCode(characterCode)
                    }
                }
            }
        } else {
            if (e.type !== "keypress") {
                return SpecialKey.fromKeyCode(e.keyCode)
            }
        }
        return undefined
    };

    function keyEntered(e) {
        e = originalEvent(e);
        var special = JIRA.Keyboard.specialKeyEntered(e);
        if (special) {
            return special
        } else {
            if ($.browser.mozilla) {
                if (e.type === "keypress") {
                    var characterCode = characterCodeForKeypress(e);
                    if (characterCode !== null) {
                        return String.fromCharCode(characterCode).toLowerCase()
                    }
                }
            } else {
                if (e.type !== "keypress") {
                    return String.fromCharCode(e.keyCode).toLowerCase()
                }
            }
        }
        return undefined
    }
    JIRA.Keyboard.shortcutEntered = function (e) {
        e = originalEvent(e);
        if (e.type === JIRA.Keyboard.SpecialKey.eventType()) {
            var specialKey = JIRA.Keyboard.specialKeyEntered(e),
                modifiers = "";
            if (e.altKey && specialKey !== SpecialKey.ALT) {
                modifiers += modifier(SpecialKey.ALT)
            }
            if (e.ctrlKey && specialKey !== SpecialKey.CTRL) {
                modifiers += modifier(SpecialKey.CTRL)
            }
            if (e.metaKey && !e.ctrlKey && specialKey !== SpecialKey.META) {
                modifiers += modifier(SpecialKey.META)
            }
            if (e.shiftKey && specialKey !== SpecialKey.SHIFT) {
                modifiers += modifier(SpecialKey.SHIFT)
            }
            if (specialKey) {
                return modifiers + specialKey
            } else {
                if (modifiers.length > 0 && modifiers !== "shift+") {
                    var key = keyEntered(e);
                    if (key) {
                        return modifiers + key
                    }
                }
            }
        }
        return undefined
    };

    function modifier(modifier) {
        return modifier + "+"
    }
})(AJS.$);
(function ($) {
    JIRA.Mouse = {};
    var MotionDetector = JIRA.Mouse.MotionDetector = function () {
            this.reset()
        };
    MotionDetector.prototype.reset = function () {
        this._handler = null;
        this._x = null;
        this._y = null;
        this.moved = false
    };
    MotionDetector.prototype.wait = function (eventHandler) {
        var instance = this;
        if (!instance._handler) {
            this.reset();
            $(window.top.document).bind("mousemove", instance._handler = function (e) {
                if (!instance._x && !instance._y) {
                    instance._x = e.pageX;
                    instance._y = e.pageY
                } else {
                    if (!(e.pageX === instance._x && e.pageY === instance._y)) {
                        instance.unbind();
                        instance.moved = true;
                        if (eventHandler) {
                            eventHandler.call(this, e)
                        }
                    }
                }
            })
        }
    };
    MotionDetector.prototype.unbind = function () {
        if (this._handler) {
            $(window.top.document).unbind("mousemove", this._handler);
            this.reset()
        }
    }
})(AJS.$);
AJS.describeBrowser = function (userAgent) {
    userAgent = userAgent || navigator.userAgent;
    var match = jQuery.uaMatch(userAgent),
        browser = match.browser,
        version = match.version.replace(/\.0$/, ""),
        classNames = [];
    classNames.push(browser);
    if (browser === "msie") {
        classNames.push(browser + "-" + version);
        version = parseInt(version);
        while (version > 6) {
            --version;
            classNames.push(browser + "-gt-" + version)
        }
    }
    jQuery("html").addClass(classNames.join(" "))
};
jQuery.fn.getOptionsFromAttributes = function () {
    var options = {};
    if (this.length) {
        jQuery.each(this[0].attributes, function () {
            var map, nodeValue = this.nodeValue,
                target = options;
            if (/^data-/.test(this.nodeName)) {
                map = this.nodeName.replace(/^data-/, "").split("."), AJS.$.each(map, function (i, propertyName) {
                    propertyName = propertyName.replace(/([a-z])-([a-z])/gi, function (entireMatch, firstMatch, secondMatch) {
                        return firstMatch + secondMatch.toUpperCase()
                    });
                    propertyName = propertyName.replace(/_([a-z]+)/gi, function (entireMatch, firstMatch) {
                        return firstMatch.toUpperCase()
                    });
                    if (i === map.length - 1) {
                        target[propertyName] = nodeValue.match(/^(tru|fals)e$/i) ? nodeValue.toLowerCase() == "true" : nodeValue
                    } else {
                        if (!target[propertyName]) {
                            target[propertyName] = {}
                        }
                    }
                    target = target[propertyName]
                })
            }
        })
    }
    return options
};
JIRA.SmartAjax = {};
(function ($) {
    JIRA.SmartAjax.SmartAjaxResult = function (xhr, requestId, statusText, data, successful, errorThrown) {
        var status = tryIt(function () {
            return xhr.status
        }, 0);
        var result = {
            successful: successful,
            status: status,
            statusText: statusText,
            errorThrown: errorThrown,
            readyState: xhr.readyState,
            hasData: data != null && data.length > 0,
            data: data,
            xhr: xhr,
            aborted: xhr.aborted,
            requestId: requestId
        };
        result.toString = function () {
            return "{\n" + "successful  : " + this.successful + ",\n" + "status      : " + this.status + ",\n" + "statusText  : " + this.statusText + ",\n" + "hasData     : " + this.hasData + ",\n" + "readyState  : " + this.readyState + ",\n" + "requestId   : " + this.requestId + ",\n" + "aborted     : " + this.aborted + ",\n" + "}"
        };
        return result
    };
    JIRA.SmartAjax.SmartAjaxResult.ERROR = "error";
    JIRA.SmartAjax.SmartAjaxResult.TIMEOUT = "timeout";
    JIRA.SmartAjax.SmartAjaxResult.NOTMODIFIED = "notmodified";
    JIRA.SmartAjax.SmartAjaxResult.PARSEERROR = "parseerror";
    JIRA.SmartAjax.makeRequest = function (ajaxOptions) {
        var _smartAjaxResult = {};
        var log = function (calltype, requestId, msg) {
                if (AJS.log) {
                    var id = requestId ? "[" + requestId + "] " : " ";
                    AJS.log("ajax" + id + calltype + " : " + msg)
                }
            };
        var generateRequestId = function () {
                var now = new Date();
                var midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
                var ms = (now.getTime() - midnight.getTime());
                return Math.max(Math.floor(ms), 1)
            };
        var errorHandler = function (xhr, statusText, errorThrown, smartAjaxResult) {
                if (!smartAjaxResult) {
                    var data = tryIt(function () {
                        return xhr.responseText
                    }, "");
                    smartAjaxResult = _smartAjaxResult = new JIRA.SmartAjax.SmartAjaxResult(xhr, _requestId, statusText, data, false, errorThrown)
                }
                log("error", smartAjaxResult.requestId, smartAjaxResult);
                if ($.isFunction(ajaxOptions.error)) {
                    ajaxOptions.error(xhr, statusText, errorThrown, smartAjaxResult)
                }
            };
        var successHandler = function (data, statusText, xhr) {
                if (xhr.status < 100) {
                    _smartAjaxResult = new JIRA.SmartAjax.SmartAjaxResult(xhr, _requestId, JIRA.SmartAjax.SmartAjaxResult.ERROR, "", false);
                    errorHandler(xhr, JIRA.SmartAjax.SmartAjaxResult.ERROR, undefined, _smartAjaxResult);
                    return
                }
                _smartAjaxResult = new JIRA.SmartAjax.SmartAjaxResult(xhr, _requestId, statusText, data, true);
                log("success", _smartAjaxResult.requestId, _smartAjaxResult);
                if ($.isFunction(ajaxOptions.success)) {
                    ajaxOptions.success(data, statusText, xhr, _smartAjaxResult)
                }
            };
        var completeHandler = function (xhr, textStatus) {
                if ($.isFunction(ajaxOptions.complete)) {
                    ajaxOptions.complete(xhr, textStatus, _smartAjaxResult)
                }
            };
        var ourAjaxOptions = {};
        for (var x in ajaxOptions) {
            ourAjaxOptions[x] = ajaxOptions[x]
        }
        ourAjaxOptions.error = errorHandler;
        ourAjaxOptions.success = successHandler;
        ourAjaxOptions.complete = completeHandler;
        var xhr = $.ajax(ourAjaxOptions);
        var _requestId = generateRequestId();
        try {
            xhr.abort = function (oldabort) {
                return function () {
                    log("aborted", _requestId, "");
                    xhr.aborted = true;
                    if ($.isFunction(oldabort)) {
                        try {
                            oldabort.call(xhr)
                        } catch (ex) {}
                    }
                }
            }(xhr.abort)
        } catch (ex) {}
        log("started", _requestId, "" + ourAjaxOptions.url);
        return xhr
    };
    JIRA.SmartAjax.buildDialogErrorContent = function (smartAjaxResult, noHeader) {
        var fourHundredClass = Math.floor(smartAjaxResult.status / 100);
        if (smartAjaxResult.hasData && fourHundredClass != 4) {
            return wrapDialogErrorContent(AJS.extractBodyFromResponse(smartAjaxResult.data))
        } else {
            var errMsg = buildRawHttpErrorMessage(smartAjaxResult);
            return buildDialogAjaxErrorMessage(errMsg, noHeader)
        }
    };
    JIRA.SmartAjax.buildSimpleErrorContent = function (smartAjaxResult) {
        return buildRawHttpErrorMessage(smartAjaxResult)
    };

    function buildRawHttpErrorMessage(smartAjaxResult) {
        var AJS = window.top.AJS;
        var errMsg;
        if (smartAjaxResult.statusText == JIRA.SmartAjax.SmartAjaxResult.TIMEOUT) {
            errMsg = AJS.params.ajaxTimeout
        } else {
            if (smartAjaxResult.status == 401) {
                errMsg = AJS.params.ajaxUnauthorised
            } else {
                if (smartAjaxResult.hasData) {
                    errMsg = AJS.params.ajaxServerError
                } else {
                    errMsg = AJS.params.ajaxCommsError
                }
            }
        }
        return errMsg
    }
    function buildDialogAjaxErrorMessage(errorMessage, noHeader) {
        var errorContent = '<div class="warningBox">' + "<p>" + errorMessage + "</p>" + "<p>" + AJS.params.ajaxErrorCloseDialog + "</p>" + "</div>";
        if (!noHeader) {
            errorContent = "<h1>" + AJS.params.ajaxErrorDialogHeading + "</h1>" + errorContent
        }
        return wrapDialogErrorContent(errorContent)
    }
    function wrapDialogErrorContent(content) {
        var $container = $('<div class="ajaxerror"/>');
        $container.append(content);
        return $container
    }
})(AJS.$);
AJS.$(function () {
    AJS.$.ajaxSetup({
        timeout: 60000,
        async: true,
        cache: false,
        global: true
    })
});
AJS.namespace("jira.ajax", null, JIRA.SmartAjax);
(function () {
    var $doc = jQuery(document);

    function getWindow() {
        var topWindow = window;
        try {
            while (topWindow.parent.window !== topWindow.window && topWindow.parent.AJS) {
                topWindow = topWindow.parent
            }
        } catch (error) {}
        return topWindow
    }
    function getLayer(instance) {
        return instance.$layer || instance.$popup || instance.$ || instance.popup
    }
    function listenForLayerEvents($doc) {
        $doc.bind("showLayer", function (e, type, item) {
            if (item && item.id && item.id.indexOf("user-hover-dialog") >= 0) {
                return
            }
            var topWindow = getWindow().AJS;
            if (topWindow.currentLayerItem && item !== topWindow.currentLayerItem && topWindow.currentLayerItem.type !== "popup") {
                topWindow.currentLayerItem.hide()
            }
            if (item) {
                topWindow.currentLayerItem = item;
                topWindow.currentLayerItem.type = type
            }
        }).bind("hideLayer", function (e, type, item) {
            if (!item || item.id && item.id.indexOf("user-hover-dialog") >= 0) {
                return
            }
            var topWindow = getWindow().AJS;
            if (topWindow.currentLayerItem) {
                if (topWindow.currentLayerItem === item) {
                    topWindow.currentLayerItem = null
                } else {
                    if (jQuery.contains(getLayer(item), getLayer(topWindow.currentLayerItem))) {
                        topWindow.currentLayerItem.hide()
                    }
                }
            }
        }).bind("hideAllLayers", function () {
            var topWindow = getWindow().AJS;
            if (topWindow.currentLayerItem) {
                topWindow.currentLayerItem.hide()
            }
        }).click(function (e) {
            var topWindow = getWindow().AJS;
            if (topWindow.currentLayerItem && topWindow.currentLayerItem.type !== "popup") {
                if (topWindow.currentLayerItem._validateClickToClose) {
                    if (topWindow.currentLayerItem._validateClickToClose(e)) {
                        topWindow.currentLayerItem.hide()
                    }
                } else {
                    topWindow.currentLayerItem.hide()
                }
            }
        })
    }
    $doc.bind("iframeAppended", function (e, iframe) {
        iframe = jQuery(iframe);
        iframe.load(function () {
            listenForLayerEvents(iframe.contents())
        })
    });
    listenForLayerEvents($doc)
})();
jQuery.fn.hasFixedParent = function () {
    var hasFixedParent = false;
    this.parents().each(function () {
        if (AJS.$(this).css("position") === "fixed") {
            hasFixedParent = true;
            return false
        }
    });
    return hasFixedParent
};